<?php
require_once 'Zend/Validate/Abstract.php';

/**
 * 日本式電話番号に適合しているかチェックします
 *
 * 参考URL:http://tenderfeel.xsrv.jp/php/zend-framework/1030/
 * @author fujiwara atsushi
 *
 */
class Validate_TelephoneNumber extends Zend_Validate_Abstract
{
	const INVALID = 'invalid';
	const NO_HYPHNATE = 'noHyphnate';
	const NO_ALLNUM = 'noAllnum';
	const NO_SMALLSIZE = 'noSmallsize';
	const NO_FULLSIZE = 'noFullsize';

	protected $_messageTemplates = array(
		self::INVALID => '書式が正しくありません。', //Invalid telephone number
		self::NO_HYPHNATE => 'ハイフンを使用してください', //Please use a hyphen
		self::NO_ALLNUM => '数字だけで記入してください', //Please enter only numbers
		self::NO_SMALLSIZE => '全角文字は使用できません', //Can not use double-byte characters
		self::NO_FULLSIZE => '半角文字は使用できません' //Can not use single-byte characters
		);

	/**
	 * @var string
	 */
	protected $_format = '';

	/**
	 * @var string
	 */
	protected $_character = '';

	/**
	 * Sets validator options
	 *
	 * $options is an array the either contains the following keys
	 *
	 * [format]
	 * hyphnate : ハイフネーションされているならtrue
	 * allnum   : 数字だけならtrue
	 * NULL     : ハイフネーションの有無を限定しない
	 *
	 * [character]
	 * small : 半角数字と半角ハイフンだけ有効
	 * full  : 全角数字と全角ハイフンだけ有効
	 * NULL  : 限定しない
	 *
	 * @param  array $option
	 * @return void
	 */
	public function __construct(array $options = array())
	{
		foreach ($options as $opt => $val) {
			$func = 'set' . ucfirst($opt);
			if (method_exists($this, $func)) {
				$this->$func($val);
			}
		}
	}

	public function setCharacter($val)
	{
		if (!empty($val)) {
			$this->_character = $val;
		}

		return $this;
	}

	public function setFormat($val)
	{

		if (!empty($val)) {
			$this->_format = $val;
		}

		return $this;
	}

	public function isValid($value)
	{

		$this->_setValue($value);

		$valueString = trim((string)$value);

		if ($this->_character === 'small') {
			if (!preg_match("/^[\d\-]+$/", $valueString)) {
				$this->_error(self::NO_SMALLSIZE);
				return false;
			}
		}

		if ($this->_character === 'full') {
			if (!preg_match("/^[０-９ー‐－]+$/", $valueString)) {
				$this->_error(self::NO_FULLSIZE);
				return false;
			}
		}

		/**
		* 日本式電話番号は「0」から開始する
		* @author fujiwara
		*/
		if(mb_substr($valueString, 0, 1) !== '0')
		{
			$this->_error(self::INVALID);
			return false;
		}

		$valueString = mb_convert_kana($valueString, "n", 'UTF-8');
		$valueString = str_replace(array('ー', '‐', '－', '―'), '-', $valueString);

		if (!preg_match("/^(\d{2,5}?\-\d{1,4}?\-\d{3,4})|(\d{10,13})$/", $valueString)) {
			$this->_error(self::INVALID);
			return false;
		}

		if (!empty($this->_format)) {
			$fnc = 'is' . ucfirst($this->_format);
			return $this->$fnc($valueString);
		}
		else {
			if (strpos($valueString, "-") === false) {
				return $this->isAllNum($valueString);
			}
			else {
				return $this->isHyphnate($valueString);
			}
		}
	}

	public function isHyphnate($value)
	{
		if (!preg_match("/(^(?<!090|080|070)(^\d{2,5}?\-\d{1,4}?\-\d{4}$|^[\d\-]{12}$))|(^(090|080|070)(\-\d{4}\-\d{4}|[\\d-]{13})$)|(^0120(\-\d{2,3}\-\d{3,4}|[\d\-]{12})$)|(^0080\-\d{3}\-\d{4})/", $value)) {
			if (!empty($this->_format)) $this->_error(self::NO_HYPHNATE);
			else $this->_error(self::INVALID);
			return false;
		}
		else {
			return true;
		}
	}

	public function isAllnum($value)
	{
		if (!preg_match("/(^(?<!090|080|070)\d{10}$)|(^(090|080|070)\d{8}$)|(^0120\d{6}$)|(^0080\d{7}$)/", $value)) {
			if (!empty($this->_format)) $this->_error(self::NO_ALLNUM);
			else $this->_error(self::INVALID);
			return false;
		}
		else {
			return true;
		}
	}
}

